3W - 실리움 기본 - IPAM

개요

이번 주차에서는 CNI로서의 실리움의 기능들을 알아보는 시간을 가진다.
공식 문서 상에서는 어디까지가 기본 기능이다, 뭐가 확장된 기능이다 이런 식으로 분류하는 것은 아니다.
image.png
다만 첫번째 탭으로 묶인 네트워킹 컨셉에 해당하는 내용들은 실리움이 CNI 프로바이더로서 제공하고자 하는 기능이 아닐까 생각했고, 실제로 기능들이 얼추 다른 CNI도 가지고 있는 기능이기도 하다.
그래서 위의 4가지 기능을 간단하게 파보는 시간을 가지려고 한다.

참고로 정말 정말 엄밀하게 말하자면 여기에서 정말 CNI가 책임져야 하는 영역은 라우팅 뿐이다.
CNI는 클러스터의 파드 간 네트워킹이 잘 이뤄지도록 경로 설정만 잘해주고, 패킷이 잘 돌아올 수 있게 NAT 작업만 잘해주면 된다.

이번 문서는 관련 개념을 훑고 바로 각각에 대한 실습을 해보는 식으로 진행한다.
이전 문서들은 사전지식을 전체적으로 훑은 후에 실습을 몰아서 하는 방식이었으나, 이번에는 다양한 모드를 순차적으로 하나씩 사용해보는 방식이기 때문이다.

실습 환경 구성

이번 실습 환경 역시 이전과 크게 다를 건 없다.
다만 라우팅, 마스커레이딩 실습에 활용하기 위해 별도의 라우터용 인스턴스를 생성한다는 점이 다르다.
image.png
(가시다님이 제작해주신 그림을 그대로 이용했다.)
클러스터의 IP 대역이 따로 있고, 이 대역이 사내망과 통신을 해야 하는 상황이다.
실제 환경이라면 라우터는 물리장비를 이용하게 될 것이다.

이를 위해 몇 가지 추가된 스크립트는 다음과 같다.

#!/usr/bin/env bash

echo ">>>> Route Add Config Start <<<<"
chmod 600 /etc/netplan/01-netcfg.yaml
chmod 600 /etc/netplan/50-vagrant.yaml

cat <<EOT>> /etc/netplan/50-vagrant.yaml
      routes:
      - to: 10.10.0.0/16
        via: 192.168.10.200
EOT

netplan apply
echo ">>>> Route Add Config End <<<<"

각 노드에서는 사내망 IP 대역으로 가기 위한 게이트웨이 경로를 명시했다.

#!/usr/bin/env bash

echo ">>>> Initial Config Start <<<<"
echo "[TASK 1] Setting Profile & Bashrc"
echo 'alias vi=vim' >> /etc/profile
echo "sudo su -" >> /home/vagrant/.bashrc
ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

echo "[TASK 2] Disable AppArmor"
systemctl stop ufw && systemctl disable ufw >/dev/null 2>&1
systemctl stop apparmor && systemctl disable apparmor >/dev/null 2>&1

echo "[TASK 3] Add Kernel setting - IP Forwarding"
sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g' /etc/sysctl.conf
sysctl -p >/dev/null 2>&1

echo "[TASK 4] Setting Dummy Interface"
modprobe dummy
ip link add loop1 type dummy
ip link set loop1 up
ip addr add 10.10.1.200/24 dev loop1

ip link add loop2 type dummy
ip link set loop2 up
ip addr add 10.10.2.200/24 dev loop2

echo "[TASK 5] Install Packages"
export DEBIAN_FRONTEND=noninteractive
apt update -qq >/dev/null 2>&1
apt-get install net-tools jq tree ngrep tcpdump arping -y -qq >/dev/null 2>&1

echo "[TASK 6] Install Apache"
apt install apache2 -y >/dev/null 2>&1
echo -e "<h1>Web Server : $(hostname)</h1>" > /var/www/html/index.html

echo ">>>> Initial Config End <<<<"

다음으로 라우터 인스턴스에서는 패킷 포워딩을 활성화하고, 사내망이라고 가정할 대역에 대한 더미 인터페이스를 추가했다.

이밖에 허블 기본 활성화, 메트릭 조회용 프로메테우스 그라파나 세팅들이 들어갔으며, 관련한 내용은 레포를 참고한다.

IPAM

IPAM이란

IP Address Management이란 용어는 네트워크에서 호스트 IP를 관리하는 작업, 혹은 시스템을 말한다.
클라우드 환경에서는 많은 가상 호스트가 동적으로 생기고 변경될 수 있기에 적절하게 서브넷 대역을 분리하고 마스크 범위를 지정하는 등의 작업을 사람의 손으로 일일히 이뤄지는 것이 힘들다.
그래서 이러한 작업을 총체적으로 설정 관리하는 시스템이 필요하게 됐으며 이에 따라 IPAM이란 개념이 대두됐다.
흔히 DNS, DHCP 프로토콜을 포함하는 기술 개념으로 생각되기도 하는 한편[1], DDI(DNS + DHCP + IPAM)이라 하여 따로 통합된 개념을 사용하는 경우도 있다.[2]
IPAM이라 했을 때 핵심적으로 포함되는 기능, 개념은 다음 정도가 있는 것 같다.

사견

개인적으로는 IPAM에 DNS까지 포함하는 것은 너무 개념을 확장시키는 것 같지만 DHCP는 IPAM 작업의 일환으로 포함될 수 있는 정도인 것 같다.
DHCP 프로토콜 상에서도 서버에 설정된 IP 풀이 있는 상태에서 사용가능한 IP를 동적으로 전달해주기 때문이다.
이렇게 봤을 때 IPAM에서 호스트에 IP를 부여하는 방법 중 하나로 DHCP 프로토콜이 있다고 이해할 수 있겠다.

실리움이 파드에 IP를 할당하는 원리

아무튼 실리움에서 제공하는 IPAM은 파드의 IP를 할당하는 기능이다.
방법은 여러 가지가 있겠으나, 기본적인 IPAM 방식은 노드 별로 IP 풀을 부여하여 독립적으로 파드 IP를 관리하는 것이다.
가령 A노드엔 172.16.1.0/16, B 노드엔 172.16.1.0/16 대역을 할당하여 각 노드에 생성되는 파드는 해당 대역 내에서 주소를 받는 식이다.

실리움은 여러 가지의 IPAM 모드를 지원하고 있는데, 먼저 어떻게 파드에 IP가 할당되는지 간단하게 짚고 넘어가자.
전체 모드를 한번에 포함시킨 도식은 이렇게 생겼다.

한번에 다양한 모드를 표현해서 복잡해 보이니 다시 정리하자면..

컨테이너 런타임은 kubelet의 요청을 받고 파드 스펙에 맞춰 컨테이너들을 위한 네임스페이스 생성 및 설정, 컨테이너 프로세스를 기동한다.
이때 네트워크 관련 설정을 위해 CNI 플러그인을 호출하고 설정 파일에 따라 CNI 플러그인은 실리움 에이전트와 통신한다.
에이전트는 모종의 방법으로(이후에 볼 예정) IP 대역을 가져오고, 파드가 사용할 IP를 하나 정한다.
그리고 에이전트는 파드에서 트래픽이 나갈 수 있도록 인터페이스를 뚫고 설정하는 갖가지 작업을 수행한다.
그 사이 IP에 대한 정보는 컨테이너 샌드박스 상태에 기록되고, 궁극적으로 kubelet이 해당 정보를 kube-apiserver에 전달하며 파드의 IP에 대한 일련의 작업이 마무리된다.

실리움 IPAM 모드

그래서 실제로 어떤 모드들이 있는지는 지금부터 알아보자.[3]
간단하게 각 모드의 차이를 표로 정리하면 이렇게 나타낼 수 있다.

Feature Kubernetes Host Scope Cluster Scope (기본) Multi-Pool (Beta) CRD-backed
Tunnel routing
Direct routing
CIDR Configuration Kubernetes Cilium Cilium External
Multiple CIDRs per cluster N/A
Multiple CIDRs per node N/A
Dynamic CIDR/IP allocation
이것 이외에도 클라우드 별로 특수한 모드들을 제공하고 있는데, 이번 노트에서는 몇 가지 모드들에 대해서만 알아보도록 한다.

참고로 이미 구성된 클러스터의 IPAM을 함부로 바꾸는 것은 권장되지 않는다.
기존 IPAM 대역과 새로 설정하는 대역 간 라우팅 설정이 제대로 되지 않을 가능성이 높아 예기치 않는 동작이 발생할 수 있다.

kubernetes host scope

기본적으로 쿠버네티스에서는 노드 별로 파드 IP 주소를 할당한다.[4]

ipam: kubernetes로 설정하면 기본 노드에 할당된 CIDR 값을 통해 파드의 ip를 관리해준다.

노드가 가지는 IP 대역?

클러스터의 노드 정보를 보면 사실 각 노드는 이미 어떤 대역을 가지고 있는 경우가 태반이다.
이것은 kube-controller-manager의 노드 컨트롤러가 노드에 대해 설정해주는 값이다.
보통 kubeadm 등으로 클러스터를 구축할 때 --allocate-node-cidrs=true(기본 활성화)와 함께 파드 IP 대역을 설정하게 된다.
이 설정 값은 컨트롤러 매니저 파드에 추가 인자로 전달되며 결과적으로 컨트롤러 매니저는 노드 컨트롤러에 해당 설정을 넣어주게 된다.
이렇게 설정된 대역을 CNI가 실제로 활용할지는 CNI 자유이며, 실리움에서는 Kubenetes Host Scope 모드에서 이 대역을 사용한다.

노드에 아래 어노테이션을 달아 직접 노드 별 cidr을 세팅하는 것도 가능하다.
image.png

실습

먼저 현재 설정된 클러스터 파드 ip 대역을 확인해본다.

kubectl describe cm -n kube-system kubeadm-config | grep network -A5
k -n kube-system get po kube-controller-manager-k8s-ctr -oyaml | grep cluster-cidr

image.png
kubeadm 세팅으로 넣었던 값은 그대로 컨트롤러 매니저에 세팅됐다.

이에 따라 각 노드에는 스펙에 해당 대역이 적히게 된다.
그리고 초기 실리움을 세팅할 때 kubernetes 모드를 지정했기 때문에 ciliumnode 리소스를 확인해보면 해당 대역을 고스란히 받은 것을 확인할 수 있다.

k get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.podCIDR}{"\n"}{end}'
k get ciliumnode -ojson | grep podCIDR -A2

image.png
image.png

image.png

트래픽 확인도 해볼 겸 실습 워크로드를 배포한다.

k apply -f check.yaml

image.png
해당 워크로드들은 이전 주차에서도 계속 활용했던 것으로 netshoot 파드와 요청을 그대로 반환해주는 워크로드로 구성돼있다.
image.png
과연 처음 설정된 IP 대역을 배정받은 것이 보인다.

사실 IPAM은 주소 할당이 끝이라 클러스터 조작으로 더 유심히 볼 만한 건 없는 것 같지만.. 그래도 통신 테스트도 간단하게 겸해보자.
이전에는 허블 릴레이 메트릭을 보고자 포트포워딩을 했지만, 다음부터는 그냥 처음부터 연결이 가능하도록 세팅을 하려고 한다.

kubectl patch svc -n kube-system hubble-relay -p '{"spec": {"type": "NodePort", "ports": [{"port": 80, "targetPort": "grpc",  "nodePort": 30004}]}}'
hubble config set server 192.168.10.100:30004
hubble status

image.png
로컬에서 vm들의 대역으로 가는 라우팅 경로만 설정해주면 노드포트 통신이 가능하단 점을 적극 활용하자.

kubectl exec -it curl-pod -- sh -c 'while true; do curl -s webpod | grep Hostname; sleep 1; done'
hubble observe -f --protocol tcp --pod curl-pod

image.png
발생한 로그를 간단하게 분석해보자.

cluster scope


기본 모드로, CiliumNode라는 커스텀 리소스에 설정된 cidr를 기반으로 노드 별 cidr을 설정한다.[7]
클러스터 차원에서 어떻게 IP 대역을 설정하건 상관 없이 실리움 차원에서 IP를 관리하기 때문에, 실리움만을 통해 네트워크 관리를 하려는 경우 관리 포인트가 조금 줄어든다.
이 리소스는 오퍼레이터가 초반에 알아서 만들어주는데 이 상태에서 알아서 조금씩 커스텀하면 된다.
기본값으로 세팅하면 10.0.0.0/8 대역을 사용하게 된다.

이때 한번 설정된 풀 자체를 수정하는 것은 권장되지 않고, 대신 그냥 새로운 대역을 할당하는 것이 추천된다.
노드 자체, 브로드 캐스트를 위해 cidr에 두 주소를 예약해버리기에 추천되는 범위는 /29 이상이다.

실습

위에서 이미 구성된 클러스터의 IPAM을 재구성하는 것이 어렵다고는 했지만, 불가능한 것은 아니다.

helm upgrade cilium cilium/cilium --namespace kube-system --reuse-values \
--set ipam.mode="cluster-pool" --set ipam.operator.clusterPoolIPv4PodCIDRList={"172.20.0.0/16"} --set ipv4NativeRoutingCIDR=172.20.0.0/16

설정이 들어간 것은 확인할 수 있다.
image.png
그러나 막상 커스텀 리소스를 보면 관련한 정보가 반영되지 않은 것을 확인할 수 있다.
image.png
해당 설정들은 컨피그맵에는 반영되지만 각 워크로드가 알아서 재기동하지 않기에 직접 재시작을 설정해줘야 한다..

kubectl -n kube-system rollout restart deploy/cilium-operator # 오퍼레이터 재시작 필요
kubectl -n kube-system rollout restart ds/cilium

그럼에도 문제는 더 있는데, 이미 만들어진 CiliumNode 리소스가 남아있다는 것이다.
image.png
아예 오퍼레이터가 설정을 제대로 못해주고 있다는 상태도 보여준다.
그래서 귀찮지만 각 CiliumNode도 직접적으로 지워주어야 한다.
image.png
그 후 에이전트를 재시작하면 비로소 설정이 반영되는 것을 확인할 수 있다.

정말 마지막으로, 현재 배치된 파드들은 새로운 IPAM의 적용을 받지 않고 있다.
image.png
에이전트는 이미 수정이 됐기에 이전 IP에 대한 처리를 제대로 할 수 없다.
따라서 워크로드들도 전부 재시작을 해주면 문제가 해결된다..

kubectl -n kube-system rollout restart deploy/hubble-relay deploy/hubble-ui
kubectl -n cilium-monitoring rollout restart deploy/prometheus deploy/grafana
kubectl -n local-path-storage rollout restart deploy/local-path-provisioner
kdelf check.yaml
kaf check.yaml

image.png
IP가 바뀌면 그때부터 제대로 트래픽 처리도 가능해진다.
image.png

multi-pool

멀티 풀은 여러 풀을 파드 별로, 네임스페이스 별로 부여할 수 있게 해주는 모드이다.

이 기능은 아직은 베타 기능으로, 추후 변동 가능성이 높다.[8]

사용 방법은 꽤나 간단한데, 이렇게 CiliumPodIPPool 리소스로 할당하고자 하는 대역을 먼저 설정한다.

apiVersion: cilium.io/v2alpha1
kind: CiliumPodIPPool
metadata:
  name: green-pool
spec:
  ipv4:
    cidrs:
      - 10.20.0.0/16
      - 10.30.0.0/16
    maskSize: 24
  ipv6:
    cidrs:
      - fd00::/104
    maskSize: 120

그 다음 파드나 네임스페이스에 ipam.cilium.io/ip-pool를 설정하여 원하는 IP 풀을 선택하여 대역을 부여받는다.
이를 설정하지 않으면 default Ip 풀을 이용하게 된다.
CiliumNode에는 다음의 정보가 표시된다.

실습 - 실패

이전과 같은 방식으로 마이그레이션을 하고 싶었으나, 많은 문제에 봉착했다.
결론적으로는 클러스터를 다시 구축하는 식으로 해결했다.
에이전트 기동이 멈추었고, 이 상태에서 재설치를 하려하자 이전의 커스텀 리소스를 계속 지웠음에도 문제가 해결되지 않았다.
image.png
실제 로그를 보면 아이덴티티를 찾을 수 없다는 말이 출력된다.
image.png
image.png
완전히 새롭게 지우고자 cleanState, cleanBpfState 옵션을 넣자 그건 또 그거대로 실행이 안 되는 이슈가 생겼다.
image.png
결과적으로 클러스터를 완전히 새로 구축해야만 했는데, 나중에 이런 상황에 대한 트러블 슈팅 방법을 조금 더 찾아봐야겠다.

설치할 때 사용한 인자는 다음과 같다.

helm install cilium cilium/cilium --version $2 --namespace kube-system \
--set k8sServiceHost=192.168.10.100 --set k8sServicePort=6443 \
--set k8s.requireIPv4PodCIDR=true --set ipv4NativeRoutingCIDR=10.244.0.0/16 \
--set ipam.mode="multi-pool" --set ipam.operator.autoCreateCiliumPodIPPools.default.ipv4.cidrs='{10.244.0.0/16}' --set ipam.operator.autoCreateCiliumPodIPPools.default.ipv4.maskSize=27 \
--set routingMode=native --set autoDirectNodeRoutes=true --set endpointRoutes.enabled=true \
--set kubeProxyReplacement=true --set bpf.masquerade=true --set installNoConntrackIptablesRules=true \
--set endpointHealthChecking.enabled=false --set healthChecking=false \
--set hubble.enabled=true --set hubble.relay.enabled=true --set hubble.ui.enabled=true \
--set hubble.ui.service.type=NodePort --set hubble.ui.service.nodePort=30003 \
--set hubble.relay.service.type=NodePort --set hubble.relay.service.nodePort=30004 \
--set prometheus.enabled=true --set operator.prometheus.enabled=true --set hubble.metrics.enableOpenMetrics=true \
--set hubble.metrics.enabled="{dns,drop,tcp,flow,port-distribution,icmp,httpV2:exemplars=true;labelsContext=source_ip\,source_namespace\,source_workload\,destination_ip\,destination_namespace\,destination_workload\,traffic_direction}" \
--set operator.replicas=1 --set debug.enabled=true >/dev/null 2>&1

image.png
아무래도 초반에 기본 default 풀이 없는 것만으로도 제대로 준비 상태가 완료되지 않아 스크립트 진행에 차질이 있는 것으로 보였다.
그래서 설치 시점에 default 풀까지는 같이 만들도록 인자를 추가해주었다.

그러나... 이 방법도 왜인지 실패했다.
설정이 반영되기는 하는 것을 볼 수 있었다.

cilium config view
k get cpip

image.png

그러나 궁극적으로 실리움 에이전트들이 제대로 기동되지 않았는데, 아래 warning 로그가 단서가 아닐까 싶긴하나 명확한 원인을 모르겠다.
image.png
문서에서 말하는 기능들은 전부 활성화했고[9], cidir 덮어쓰우기, ipsec 등의 설정은 일체 하지 않았다.
내가 활성화한 값 중 문서에서 언급되지 않은 충돌 소지가 있는 어떤 기능이 있는 게 아닐까 싶은데 이 부분은 명확하지 않아 넘어가고자 한다.

결론

실제 서비스 중인 클러스터에 대해서는 영향도 없이 마이그레이션하는 것이 거의 불가능할 것 같다.
IP 풀을 바꾸는 순간 통신이 불가능해지는 이상은 그렇다.

그렇기 때문에 IP 대역이 부족해질 것이 염려된다면 처음부터 유동적으로 설정이 가능한 기본 모드를 쓰거나 multi-pool 모드를 사용하는 게 좋아보인다.
아울러 변경이 필요하다면 클러스터 째로 업그레이드하는 방식으로 운용해야 하며 이를 위해 평소에 파드 개수를 모니터링 항목으로 포함시켜두어야 할 것이다.

이전 글, 다음 글

다른 글 보기

이름 index noteType created
1W - 실리움 기본 소개 1 published 2025-07-19
1W - 클러스터 세팅 및 cni 마이그레이션 2 published 2025-07-19
1W - 기본 실리움 탐색 및 통신 확인 3 published 2025-07-19
2W - 허블 기반 모니터링 4 published 2025-07-26
2W - 프로메테우스와 그라파나를 활용한 모니터링 5 published 2025-07-26
3W - 실리움 기본 - IPAM 6 published 2025-08-02
3W - 실리움 기본 - Routing, Masq, IP Frag 7 published 2025-08-02
4W - 실리움 라우팅 모드 실습 - native, vxlan, geneve 8 published 2025-08-09
4W - 실리움 로드밸런서 기능 - 서비스 IP, L2 9 published 2025-08-09

하위 문서

이름 is-folder index noteType created
1W - 실리움 기본 소개 false 1 published 2025-07-19
1W - 클러스터 세팅 및 cni 마이그레이션 false 2 published 2025-07-19
1W - 기본 실리움 탐색 및 통신 확인 false 3 published 2025-07-19
2W - 허블 기반 모니터링 false 4 published 2025-07-26
2W - 프로메테우스와 그라파나를 활용한 모니터링 false 5 published 2025-07-26
3W - 실리움 기본 - IPAM false 6 published 2025-08-02
3W - 실리움 기본 - Routing, Masq, IP Frag false 7 published 2025-08-02
4W - 실리움 라우팅 모드 실습 - native, vxlan, geneve false 8 published 2025-08-09
4W - 실리움 로드밸런서 기능 - 서비스 IP, L2 false 9 published 2025-08-09

관련 문서

지식 문서, EXPLAIN

이름5is-folder생성 일자
설치 요구사항false2025-07-06 10:34
ebpf 동작 가이드false2025-07-06 10:49
Hubblefalse2025-07-06 10:38
0주차 검증false2025-07-06 12:46
Ciliumfalse2025-06-15 23:42

기타 문서

Z0-연관 knowledge, Z1-트러블슈팅 Z2-디자인,설계, Z3-임시, Z5-프로젝트,아카이브, Z8,9-미분류,미완
이름16코드타입생성 일자
4W - 실리움 로드밸런서 기능 - 서비스 IP, L2Z8published2025-08-09 21:56
4W - 실리움 라우팅 모드 실습 - native, vxlan, geneveZ8published2025-08-09 20:22
1W - 실리움 기본 소개Z8published2025-07-19 22:44
실리움 1주차Z8topic2025-07-13 19:50
실리움 개괄Z8topic2025-07-19 11:00
기본 실리움 탐색 및 통신 확인Z8topic2025-07-19 23:05
클러스터 세팅 및 cni 마이그레이션Z8topic2025-07-19 10:13
실리움 2주차Z8topic2025-07-20 19:05
노드로컬 dnsZ8topic2025-08-02 12:57
실리움 3주차Z8topic2025-07-27 19:44
1W - 클러스터 세팅 및 cni 마이그레이션Z8published2025-07-19 23:38
1W - 기본 실리움 탐색 및 통신 확인Z8published2025-07-19 23:45
3W - 실리움 기본 - Routing, Masq, IP FragZ8published2025-08-02 22:23
Cilium 공식 문서 핸즈온 스터디Z8published2025-07-05 20:47
2W - 프로메테우스와 그라파나를 활용한 모니터링Z8published2025-07-26 21:15
2W - 허블 기반 모니터링Z8published2025-07-26 21:08

참고


  1. https://www.infoblox.com/glossary/ipam-ip-address-management/ ↩︎

  2. https://efficientip.com/glossary/what-is-ddi/ ↩︎

  3. https://docs.cilium.io/en/stable/network/concepts/ipam/ ↩︎

  4. https://docs.cilium.io/en/stable/network/concepts/ipam/kubernetes/ ↩︎

  5. https://community.cisco.com/t5/network-security/what-does-mean-term-xlate/td-p/1266100 ↩︎

  6. https://docs.cilium.io/en/stable/network/kubernetes/kubeproxy-free/#observability ↩︎

  7. https://docs.cilium.io/en/stable/network/concepts/ipam/cluster-pool/ ↩︎

  8. https://docs.cilium.io/en/stable/network/concepts/ipam/multi-pool/ ↩︎

  9. https://docs.cilium.io/en/stable/network/kubernetes/ipam-multi-pool/#validate-installation ↩︎